package com.cancer.common.util;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

/**
 * 字符串工具
 *
 * @author 刘俊
 * @time 2015年1月19日
 */
public final class StringUtil {
	private static final char SEPARATOR = '_';
	private static final String LETTER = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";

	/**
	 * 将驼峰式字串转为下划线式字串
	 *
	 * <pre>
	 * 		1. IOSPersent 		--> iosPersent
	 * 		2. helloWorld 		--> helloWorld
	 * 		3. HelloWorld 		--> helloWorld
	 * </pre>
	 *
	 * @author 刘俊 2015年5月6日
	 * @param str 要转换的字串
	 * @return 下划线式字串
	 */
	public static String toUnderlineName(String str) {
		if (str == null) {
			return null;
		}

		StringBuilder sb = new StringBuilder();
		boolean upperCase = false;
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);

			boolean nextUpperCase = true;

			if (i < (str.length() - 1)) {
				nextUpperCase = Character.isUpperCase(str.charAt(i + 1));
			}

			if ((i >= 0) && Character.isUpperCase(c)) {
				if (!upperCase || !nextUpperCase) {
					if (i > 0) {
						sb.append(SEPARATOR);
					}
				}
				upperCase = true;
			} else {
				upperCase = false;
			}

			sb.append(Character.toLowerCase(c));
		}

		return sb.toString();
	}

	/**
	 * 将下划线转为驼峰式字串
	 *
	 * <pre>
	 * 		1. IOSPersent 		--> iospersent
	 * 		2. IOS_Persent 		--> iosPersent
	 * 		3. IOS_Pers__ent	--> iosPersEnt
	 * </pre>
	 *
	 * @author 刘俊 2015年5月6日
	 * @param str
	 * @return
	 */
	public static String toCamelCase(String str) {
		if (str == null) {
			return null;
		}

		str = str.toLowerCase();

		StringBuilder sb = new StringBuilder(str.length());
		boolean upperCase = false;
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);

			if (c == SEPARATOR) {
				upperCase = true;
			} else if (upperCase) {
				sb.append(Character.toUpperCase(c));
				upperCase = false;
			} else {
				sb.append(c);
			}
		}

		return sb.toString();
	}

	public static String toCapitalizeCamelCase(String s) {
		if (s == null) {
			return null;
		}
		s = toCamelCase(s);
		return s.substring(0, 1).toUpperCase() + s.substring(1);
	}

	/**
	 * 判断String是否为空指针或空串
	 *
	 * @author 刘俊 2015年4月15日
	 * @param str
	 * @return 空指针或空串返回true
	 */
	public static boolean isEmpty(String str) {

		return (str == null) || "".equals(str);
	}

	/**
	 * 判断String是否为不为空串
	 *
	 * @author 刘俊 2015年4月15日
	 * @param str
	 * @return
	 */
	public static boolean isNotEmpty(String str) {

		return (str != null) && !"".equals(str);

	}

	/**
	 * 判断数组引用是否为空，长度是否为0，且判断数组里的元素是否都为空
	 *
	 * @author 刘俊 2015年3月17日
	 * @param array
	 * @return
	 */
	public static boolean isArrayAndElememtEmpty(String[] array) {
		if ((array == null) || (array.length == 0)) {
			return true; // 长度、引用为空
		} else {
			for (String e : array) {
				if (!isEmpty(e)) {
					return false; // 如果数组中有值不为空
				}
			}

			return true; // 都为空
		}
	}

	public static String trim(String str) {
		if (str == null) {
			return null;
		} else {
			return str.trim();
		}
	}

	/**
	 * 删除左右两边指定的字串
	 *
	 * @param str
	 * @param p
	 * @return
	 */
	public static String trim(String str, String p) {
		while (str.indexOf(p) == 0) {
			str = str.substring(p.length());
		}
		while (str.lastIndexOf(p) == (str.length() - p.length())) {
			str = str.substring(0, str.length() - p.length());
		}

		return str;
	}

	/**
	 * 左边删除 @param p1, 右边删除 @param p2
	 *
	 * @author 刘俊 2015年1月19日
	 * @param str
	 * @param p1 若为null或空串, 则不进行删除
	 * @param p2 若为null或空串, 则不进行删除
	 * @return
	 */
	public static String trim(String str, String p1, String p2) {
		while (!isEmpty(p1) && (str.indexOf(p1) == 0)) {
			str = str.substring(p1.length());
		}
		while (!isEmpty(p2) && (str.lastIndexOf(p2) == (str.length() - p2.length()))) {
			str = str.substring(0, str.length() - p2.length());
		}

		return str;
	}

	/**
	 * 判断两个字符串是否相等，都为null也相等
	 */
	public static boolean equals(String str1, String str2) {
		try {
			if (str1 == str2) {
				return true;
			} else {
				return str1.equals(str2);
			}
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 格式化对象
	 *
	 * @param obj
	 * @return
	 */
	public static String formatObjectToString(Object obj) {
		if (obj != null) {
			return String.valueOf(obj).trim();
		} else {
			return null;
		}
	}

	public static String firstCharLowerCase(String str) {
		return str.substring(0, 1).toLowerCase() + str.substring(1);
	}

	public static String firstCharUpperCase(String str) {
		return str.substring(0, 1).toUpperCase() + str.substring(1);
	}

	/**
	 * 生成指定长度的随机串
	 *
	 * @autohr 刘俊
	 * @date 2015年12月9日
	 * @param length
	 * @return
	 */
	public static String getRandomString(int length) {

		return getRandomString(length, length);
	}

	/**
	 * 生成指定长度范围的随机串
	 *
	 * @autohr 刘俊
	 * @date 2015年12月9日
	 * @param min 最小长度
	 * @param max 最大长度
	 * @return
	 */
	public static String getRandomString(int min, int max) {
		// 参数不正确时不抛出异常
		if (min < 0) {
			min = 1;
		}
		if (min > max) {
			min = max;
		}

		StringBuffer ranStr = new StringBuffer();

		Random random = new Random();
		int length = (random.nextInt(max) % ((max - min) + 1)) + min;

		// 生成随机类
		for (int i = 0; i < length; ++i) {
			String ranChar = String.valueOf(LETTER.charAt(random.nextInt(LETTER.length())));
			ranStr.append(ranChar);
		}

		return ranStr.toString();
	}

	/**
	 * 统计字符出现的次数
	 *
	 * @autohr 刘俊 2016年2月22日
	 * @param str 字符串
	 * @param word 字符
	 * @return
	 */
	public static int countingWord(String str, String word) {
		int i = 0;
		for (int j = -1; (j = str.indexOf(word, j + 1)) != -1; i++) {
		}

		return i;
	}

	/**
	 * 生成一个uuid的串
	 *
	 * @author 刘俊 2016年4月1日
	 * @return
	 */
	public static String UUID() {

		return java.util.UUID.randomUUID().toString().replaceAll("-", "");
	}

	/**
	 * 转换基础数据类型<br>
	 * NOTE: 经测试该转换方法比原生的Integer.parseInt()、Double.parseDouble()等方法慢约至少30%<br>
	 *
	 * @autohr 刘俊
	 * @date 2016年1月5日
	 * @param type 目标类型
	 * @param src 要转换的值
	 * @return 成功返回正确数值，失败返回null
	 */
	@SuppressWarnings("unchecked")
	public static <T> T parseBaseType(Class<T> type, Object src) {
		try {
			Constructor<?> con = type.getDeclaredConstructor(String.class);
			return (T) con.newInstance(src.toString());
		} catch (Exception e1) {
			return null;
		}
	}

	/**
	 * 转换基础数据类型<br>
	 * NOTE: 经测试该转换方法比原生的Integer.parseInt()、Double.parseDouble()等方法慢约至少30%<br>
	 *
	 * @autohr 刘俊
	 * @date 2016年1月5日
	 * @param type 目标类型
	 * @param src 要转换的值
	 * @param defaultValue 默认值
	 * @return 成功返回正确数值，失败返回默认数值
	 */
	public static <T> T parseBaseType(Class<T> type, Object src, T defaultValue) {
		try {
			return parseBaseType(type, src);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}

	/**
	 * 将对象转换为Integer。先调用toString，再对字符串进行转换
	 *
	 * @author 刘俊 2016年3月18日
	 * @param src
	 * @return 转换出现异常则返回null
	 */
	public static Integer parseInt(Object src) {
		try {
			return Integer.parseInt(src.toString());
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 将对象转换为Integer。先调用toString，再对字符串进行转换
	 *
	 * @author 刘俊 2016年3月18日
	 * @param src
	 * @return 成功返回正确数值，失败返回defaultValue
	 */
	public static Integer parseInt(Object src, int defaultValue) {
		if(src==null){
			return defaultValue;
		}
		try {
			return Integer.parseInt(src.toString());
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 将对象转换为Long。先调用toString，再对字符串进行转换
	 *
	 * @author 刘俊 2016年3月18日
	 * @param src
	 * @return 成功返回正确数值，失败返回null
	 */
	public static Long parseLong(Object src) {
		try {
			return Long.parseLong(src.toString());
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 将对象转换为Long。先调用toString，再对字符串进行转换
	 *
	 * @author 刘俊 2016年3月18日
	 * @param src
	 * @param defaultValue
	 * @return 成功返回正确数值，失败返回defaultValue
	 */
	public static Long parseLong(Object src, long defaultValue) {
		try {
			return Long.parseLong(src.toString());
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 将逗号分隔的字符串转为LIST
	 *
	 * @author qiunan 2016年5月16日
	 * @param arr
	 * @return
	 */
	public static List<String> arrStrToList(String arrStr) {
		List<String> resultList = new ArrayList<String>();

		String[] arr = arrStr.split(",");
		for (String tempCode : arr) {
			if (StringUtils.isNotEmpty(tempCode.trim())) {
				resultList.add(tempCode.trim());
			}
		}
		return resultList;
	}

	/**
	 * 判断是否包含中英文特殊字符，除英文"-_"字符外
	 *
	 * @author qiunan 2016年7月21日
	 * @param text
	 * @return
	 */
	public static boolean isContainsSpecialChar(String text) {
		if (StringUtils.isBlank(text)) {
			return false;
		}
		String[] chars = { "[", "`", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "+", "=", "|", "{", "}", "'", ":", ";", "'",
				",", "[", "]", ".", "<", ">", "/", "?", "~", "！", "@", "#", "￥", "%", "…", "&", "*", "（", "）", "—", "+", "|", "{", "}", "【",
				"】", "‘", "；", "：", "”", "“", "’", "。", "，", "、", "？", "]" };
		for (String ch : chars) {
			if (text.contains(ch)) {
				return true;
			}
		}
		return false;
	}

	//根据Unicode编码完美的判断中文汉字和符号
	public static boolean isChinese(char c) {
		Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
		if ((ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) || (ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS)
				|| (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A)
				|| (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B)
				|| (ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION)
				|| (ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) || (ub == Character.UnicodeBlock.GENERAL_PUNCTUATION)) {
			return true;
		}
		return false;
	}

	/**
	 * 获取字符串长度，中文2字符、英文1字符
	 * 
	 * @author qiunan 2016年7月21日
	 * @param s
	 * @return
	 */
	public static int getStrlength(String s) {
		if (s == null) {
			return 0;
		}
		char[] c = s.toCharArray();
		int len = 0;
		for (int i = 0; i < c.length; i++) {
			len++;
			if (isChinese(c[i])) {
				len++;
			}
		}
		return len;
	}

	/**
	 * 按真实字符串长度进行截取字符串
	 * 
	 * @author qiunan 2016年7月21日
	 * @param str
	 * @param subSize 截取长度
	 * @return
	 */
	public static String subStringByRealLen(String str, int subSize) {
		StringBuffer resultStr = new StringBuffer();
		if (null != str) {
			char[] c = str.toCharArray();

			//迭代字符数组
			int charLen = 0;
			for (int i = 0; i < c.length; i++) {
				charLen++;
				if (isChinese(c[i])) {
					charLen++;
				}
				//判断当前长度是否达到截取长度
				if (charLen >= subSize) {
					if (charLen > subSize) {
						resultStr.append(str.substring(0, i));
					} else {
						resultStr.append(str.substring(0, i + 1));
					}
					break;
				}
			}
			if (charLen < subSize) {
				resultStr.append(str);
			}
			
		}
		return resultStr.toString();
	}
	
	/**
     * 匹配正浮点数,2位小数
     * 
     * @param str
     * @return
     * @author jiqinlin
     */
    public final static boolean isFloat(String str) {
        return match(str, "^[0-9]+(.[0-9]{1,2})?$");
    }
    
    /**
     * 正则表达式匹配
     * 
     * @param text 待匹配的文本
     * @param reg 正则表达式
     * @return
     * @author jiqinlin
     */
    public final static boolean match(String text, String reg) {
        if (StringUtils.isBlank(text) || StringUtils.isBlank(reg))
            return false;
        return Pattern.compile(reg).matcher(text).matches();
    }
    
    /**
	 * 正则表达式匹配
	 * @author liudezhu 2017年9月21日
	 * @param str
	 * @param regex
	 * @return
	 */
	public static boolean matches(String str,String regex){
		if(StringUtils.isNoneBlank(str) && StringUtils.isNoneBlank(regex)){
			return str.matches(regex);
		}
		return false;
	}
	
	/**
	 * 是否包含中文
	 * @author chengxianghong 2017年12月7日
	 * @param str
	 * @return
	 */
	public static boolean isContainChinese(String str) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        if (m.find()) {
            return true;
        }
        return false;
    }
}
